package com.jwd.comm;

import com.sun.org.apache.xpath.internal.operations.Bool
import java.lang.StringBuilder
import java.util.*;
import java.util.function.*;

/**
 * Created by udi on 2015/9/25.
 */

object MyString {
    /**
     * 暗文（不显示字符）的 列分隔符。
     */
    val SplitCell = 1.toChar();
    /**
     * 暗文（不显示字符）的 行分隔符。
     */
    var SplitLine = 2.toChar();
    /**
     * 暗文（不显示字符）的 段分隔符。
     */
    val SplitSect = 3.toChar();

    /**
     * 暗文（不显示字符）的 逗号替换符分隔符。
     */
    val SplitComma = 4.toChar();

    /**
     * 暗文（不显示字符）的 引用替换符。
     */
    val SplitQuotes = 5.toChar();

    /**
     * 暗文（不显示字符）的 分号替换符。
     */
    val SplitSemicolon = 6.toChar();

    /**
     * 暗文（不显示字符）的 百分号替换符。
     */
    val SplitPercent = 7.toChar();
}

fun <T> Array<out T>.Join(separator: CharSequence = ","): String {
    return this.joinToString(separator);
}

/*
使C#的方式进行格式化输出 。
 */
fun String.Format(vararg args: Any?): String {
    var FormatValue = this;
    if (FormatValue == null) return "";

    for (i in args.indices) {
        FormatValue = FormatValue.replace("{" + i.toString() + "}", args[i]?.toString() ?: "");
    }

    return FormatValue;
}

fun String?.MySplit(vararg splitChar: Char): Array<String> {
    var list = mutableListOf<String>()
    if (this == null) return list.toTypedArray();
    if (this == "") return list.toTypedArray();

    if (splitChar.any() == false) {
        list.add(this!!);
        return list.toTypedArray();
    }

    var i = -1;
    var prevIndex = 0;
    while (true) {
        i++;
        if (i >= this.length) break;

        var item = this.get(i);
        if (splitChar.contains(item)) {
            var sect = this.slice(prevIndex..i - 1);
            if (sect.length != 0) {
                list.add(sect);
            }

            prevIndex = i + 1;
            continue;
        }
    }
    return list.toTypedArray();
}

fun String?.Contains(func: (Char) -> Boolean): Boolean {
    if (this == null) return false;
    if (this.length == 0) return false;
    this.forEach {
        if (func(it)) {
            return true;
        }
    }

    return false;
}

/**
 * 可以为负数
 */
fun String?.Slice(startIndex: Int, endIndex: Int = 0): String {
    if (this == null) return "";
    if (startIndex < 0) return this.Slice(this.length + startIndex, endIndex);
    if (endIndex <= 0) return this.Slice(startIndex, this.length + endIndex);

    return this.slice(startIndex..endIndex)
}

fun String.TakeOut(BeginSign: String, EndSign: String, StartIndex: Int = 0): String {
    if (this == null) return "";

    var start1 = this.indexOf(BeginSign, StartIndex);
    if (start1 < 0) return "";
    var start2 = this.indexOf(EndSign, StartIndex + BeginSign.length);
    if (start2 < 0) return "";
    return this.slice(start1..start2);
}

fun String?.Is(other: String): Boolean {
    if (this == null) return false;
    return this.compareTo(other, true) == 0;
}

fun String?.IsNumberic(): Boolean {
    if (this == null) return false;
    if (this.length == 0) return false;

    var hasDot = false;
    var hasSigne = false;
    this.all {
        if (it == '.') {
            if (hasDot == false) {
                hasDot = true;
                return@all true;
            }
            return false;
        }
        if (it == '+' || it == '-') {
            if (hasSigne == false) {
                hasSigne = true;
                return@all true;
            }
            return false;
        }

        if (it.isDigit()) {
            return@all true;
        }
        return false;

        return@all true;
    }

    return true;
}

fun String.TrimWithPair(removeStart: String, removeEnd: String): String {
    if (this.isEmpty()   || removeStart.isEmpty()  || removeEnd.isEmpty()  )
        return this;

    var self = this.trim();
    var removeStart = removeStart.trim();
    var removeEnd = removeEnd.trim();

    if (self.startsWith(removeStart) && self.endsWith(removeEnd)) {
        self = self.substring(removeStart.length, self.length - removeEnd.length);

        if (self.startsWith(removeStart) && self.endsWith(removeEnd)) {
            self = self.TrimWithPair(removeStart, removeEnd);
        }
    }

    return self.trim();
}


fun String.MySplit_QuoteAs1(splitChar: Char): List<String> {
    var Source = this;
    var ret = mutableListOf<String>()
    if (Source == null) return ret;
    if (Source.length == 0) {
        ret.add("");
        return ret;
    }


    var quoteChar = 0.toChar();
    var finded = false;
    var prevIndex = 0;

    var i = -1;
    while (true) {
        i++;
        if (i >= Source.length) break;

        var item = Source.get(i);

        if (finded) {
            if (quoteChar == item && i > 0 && (Source.get(i - 1) != '\\')) {
                finded = false;
            }

            continue;
        }


        if (item == '"' || item == '\'') {
            if (finded == false) {
                quoteChar = item;
                finded = true;
                continue;
            }
        } else if (item == splitChar) {
            ret.add(Source.Slice(prevIndex, i));

            prevIndex = i + 1;
        }
    }


    if (prevIndex < Source.length) {
        ret.add(Source.Slice(prevIndex, Integer.MAX_VALUE));
    }

    return ret;
}


/// <summary>
/// 在非字符串范围查找下一个可能字符的位置，如果找不到，返回最末尾的位置。
/// </summary>
/// <remarks>在查找过程中，跳过成对的字符串标志。</remarks>
/// <param name="Value"></param>
/// <param name="index"></param>
/// <param name="findChar"></param>
/// <returns></returns>
fun String.GetIndexChar_SkipInQuote(index: Int, vararg findChar: Char): Int {
    /*
    * 规则：
    * 1. 反斜线是转义，反斜线后面的字符可忽略规则。
    * 2. 双引号是整体,单引号是整体
    */
    var Value = this;
    //结束
    if (index == this.length) return -1;
    if (index < 0) return -1;

    var tmpPos = 0;
    var i = index - 1;
    while (true) {
        i++;
        if (i >= this.length) break;
        var item = Value.get(i);
        if (item == '\\') {
            i++;
            continue;
        }

        if (item == '\'') {
            tmpPos = Value._getNextChar(  i + 1, '\'');
            if (tmpPos < 0) return tmpPos;

            i = tmpPos;
            continue;
        }

        if (item == '"') {
            tmpPos = Value._getNextChar(  i + 1, '"');
            if (tmpPos < 0) return tmpPos;

            i = tmpPos;
            continue;
        }


        if (findChar.contains(item)) {
            return i;
        }
    }


    return -1;
}

fun String.GetIndexString_SkipInQuote(index: Int, vararg findStrings: String): Int {
    var Value = this;
    if (index == Value.length) return -1;
    if (index < 0) return -1;

    var tmpPos = 0;

    var i = index - 1;
    while (true) {
        i++;
        if (i >= Value.length) break;

        var item = Value.get(i);
        if (item == '\\') {
            i++;
            continue;
        }

        if (item == '\'') {
            tmpPos = Value._getNextChar(  i + 1, '\'');
            if (tmpPos < 0) return tmpPos;

            i = tmpPos;
            continue;
        }

        if (item == '"') {
            tmpPos = Value._getNextChar(  i + 1, '"');
            if (tmpPos < 0) return tmpPos;

            i = tmpPos;
            continue;
        }

        for (findString in findStrings) {
            if (Value.IsMatch(i, findString)) {
                return i;
            }
        }
    }


    return -1;
}

private fun String._getNextChar( index: Int, findChar: Char): Int {
    var html = this;
    var len = html.length ;
    var index = index - 1;

    while (true) {
        index++;
        if (index >= len) break;


        if (html.get(index) == '\\') {
            index++;
            continue;
        }

        if (html.get(index) == findChar) {
            return index;
        }
    }

    return -1;
}

fun String.TrimEnd(vararg removeEnd: Char): String {
    var value = this;

    if (value.length == 0) return "";

    var last = value.get(value.length - 1);

    if (removeEnd.contains(last) ) {
        return value.substring(0, value.length - 1).TrimEnd(*removeEnd);
    }

    return value;
}


fun String.IsMatch(Index: Int, MatchString: String): Boolean {
    if ((Index + MatchString.length) > this.length) return false;

    for (i in 0..MatchString.length - 1) {
        if (this.get(Index + i) != MatchString.get(i)) return false;
    }

    return true;
}

fun String.ToJsonValueString(): String {
    return this
            .replace("\\", "\\\\")
            .replace("\n", "\\n")
            .replace("\r", "\\r")
            .replace("\t", "\\t")
            .replace("\"", "\\\"")
    //.Replace("\'", "\\'")
    ;
}

fun String.SplitWithSeperator(vararg splitString: String): MutableList<String> {
    var Source = this;
    var list = mutableListOf<String>()

    var lastPos = 0;
    var i = 0;
    while (true) {
        i++;
        if (i >= Source.length) break;

        for (j in 0..splitString.size - 1) {
            var item = splitString[j];
            if (Source.IsMatch(i, item)) {

                list.add(Source.slice(lastPos..i - 1));
                lastPos = i;
                break;
            }
        }
    }

    if (lastPos < Source.length) {
        list.add(Source.slice(lastPos..Source.length));
    }

    return list;
}

fun String.GetEmptyCharIndex_SkipInQuote(index: Int): Int {
    return this.GetIndexChar_SkipInQuote(index, ' ', '\t', '\r', '\n');
}

fun String.GetNotEmptyCharIndex(index: Int): Int {
    var Value = this;
    var i = index - 1;
    while (true) {
        i++;
        if (i >= Value.length) break;

        var item = Value.get(i);
        if (item == ' ') continue;
        if (item == '\t') continue;
        if (item == '\r') continue;
        if (item == '\n') continue;

        return i;
    }

    return -1;
}


fun String.RemoveComment(): String {
    var str = this;
    //去除注释
    var i = -1;
    while (true) {
        i++;
        if (i >= str.length) break;

        var next = str.GetIndexString_SkipInQuote(i, "//", "/*");
        if (next < 0) break;

        if (str.IsMatch(next, "//")) {
            var lineEnd = str.indexOf('\n', next);
            if (lineEnd < 0) {
                str = str.substring(0, next);
                break;
            } else {
                str = str.substring(0, next) + str.substring(lineEnd + 1);
            }
        } else {
            var end = str.indexOf("*/", next);
            if (end < 0) {
                str = str.substring(0, next);
                break;
            } else {
                str = str.substring(0, next) + str.substring(end + 2);
            }
        }

        i = next - 1;
    }

    return str;
}


fun String.IndexOf(FindString: String, startIndex: Int, match: (Int) -> Boolean): Int {
    //if (string.IsNullOrEmpty(FindString)) throw new GodError("字符串的探测长度必须大于0");

    if (this.length == 0) return -1;

    var len = FindString.length;
    if (len == 0) return -1;

    var startIndex = startIndex;

    while (true) {
        var index = this.indexOf(FindString, startIndex);
        if (index < 0) break;

        startIndex = index + len;

        if (match(index)) {
            return index;
        }
    }

    return -1;
}


fun Char.NewString(count: Int): String {
    var chrs = StringBuilder();

    for (i in 0..count - 1) {
        chrs.append(this);
    }

    return chrs.toString();
}